package com.fy.common.spring.aop;

import com.alibaba.fastjson.JSON;
import com.fy.common.exception.BusinessException;
import com.fy.common.model.ResponseResult;
import com.fy.common.spring.I18nHelper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
@Slf4j
public class ResponseAspect {

    /**
     * controller拦截规则
     */
    @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
    public void controllerAspect() {

    }

    @Around("controllerAspect()")
    public Object ControllerInterceptor(ProceedingJoinPoint joinPoint) throws Throwable{
        long startTime = System.currentTimeMillis();
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String classType = joinPoint.getTarget().getClass().getName();
        Class<?> clazz = null;
        try {
            clazz = Class.forName(classType);
        } catch (ClassNotFoundException e) {
            log.error("Class.forName({}),error:{}", classType, e);
        }
        //打印参数
        this.logParam(args, signature, clazz);
        long usedTime = System.currentTimeMillis() - startTime;
        log.info("aop compute method[{}] use time:{} milliseconds. ", signature.toShortString(), usedTime);
        return joinPoint.proceed();
//        try {
//            long usedTime = System.currentTimeMillis() - startTime;
//            log.info("aop compute method[{}] use time:{} milliseconds. ", signature.toShortString(), usedTime);
//            return joinPoint.proceed();
//        } catch (Throwable throwable) {
//            ResponseResult<?> responseResult = handlerException(signature, clazz, throwable);
//            long usedTime = System.currentTimeMillis() - startTime;
//            log.info("aop compute method[{}] use time:{} milliseconds. ", signature.toShortString(), usedTime);
//            return responseResult;
//        }
    }

    /**
     * 打印参数
     * @param args
     * @param signature
     * @param clazz
     */
    private void logParam(Object[] args, MethodSignature signature, Class<?> clazz) {
        String clazzName = clazz.getName();
        String[] paramNames = signature.getParameterNames();
        try {
            Map<String, Object> map = new HashMap<>();
            for (int i = 0; i < args.length; i++) {
                /**
                 * 上传的文件,排除掉
                 */
                if (args[i] instanceof MultipartFile) {
                    continue;
                }
                map.put(paramNames[i], args[i]);
            }
            log.info("aop className[{}] method[{}],params:{}", clazzName, signature.toShortString(), JSON.toJSONString(map));
        } catch (Exception e) {
            log.error("aop logParam,error:{}", e);
        }
    }

    /**
     * 处理异常
     * @param signature
     * @param clazz
     * @param e
     * @return
     */
    private ResponseResult<?> handlerException(MethodSignature signature, Class<?> clazz, Throwable e) {
        e.printStackTrace();
        //业务异常
        if (e instanceof BusinessException) {
            BusinessException ex = (BusinessException) e;
            String errMsg = I18nHelper.getMessage(ex.getErrorType().getErrorKey(), ex.getParam());
            log.info("aop className[{}] method[{}], business exception:{}-{}", clazz.getName(), signature.getMethod(), ex.getErrorType().getErrorCode(), errMsg);
            return ResponseResult.fail(ex.getErrorType().getErrorCode(), errMsg);
        }
        log.error("aop className[{}] method[{}], business exception:{}", clazz.getName(), signature.getMethod(), e.getMessage());
        return ResponseResult.fail("The server is running out...");
    }
}
